/* Copyright 2012 Dustin Mitchell <dmmitche [at] gmail [dot] com>
 *
 * Licensed under the GPLv3.  See included LICENSE.txt for full details.
 */

#include "sensor_service.h"
#include "message_queue.h"
#include "message_handler.h"
#include "messages.h"
#include "sensor.h"
#include "sensor_manager.h"
#include "log.h"

void sensor_service (struct message_queue *msg_queue, void *user_obj)
{
  struct sensor_svc_args *args = (struct sensor_svc_args *)user_obj;
  struct message_handler msg_handler;
  struct sensor_manager sensor_mgr;
  int n_registered;
  volatile int run = 1;

  if (!args) {
    log (LOG_ERR, "invalid param");
    return;
  }

  if (message_handler_create (&msg_handler) == -1) {
    log (LOG_ERR, "unable to create message handler");
    return;
  }

  if (message_queue_register_handler (msg_queue, &msg_handler, QUIT_MESSAGE)
      == -1) {
    log (LOG_ERR, "unable to register message handler");
    goto out1;
  }

  if (sensor_manager_create (&sensor_mgr) == -1) {
    log (LOG_ERR, "unable to create snensor manager");
    goto out2;
  }

  for (n_registered = 0; n_registered < args->n_sensors; ++n_registered) {
    if (sensor_manager_register (&sensor_mgr, &args->sensors[n_registered],
                                 n_registered) == -1) {
      log (LOG_ERR, "unable to register sensor with manager");
      goto out3;
    }
  }

  log (LOG_INFO, "sensor service started");

  while (run) {
    union message msg;
    int got_msg;
    int sensor_id;

    sensor_id = sensor_manager_read (&sensor_mgr, &msg.sensor.reading);
    if (sensor_id == -1) {
      log (LOG_ERR, "error reading sensor");
      break;
    }

    msg.header.type = SENSOR_MESSAGE;
    msg.sensor.sensor_id = sensor_id;

    if (message_queue_post (msg_queue, &msg) == -1)
      log (LOG_WARNING, "unable to post sensor message");

    got_msg = message_handler_peek (&msg_handler, &msg);

    if (got_msg == -1) {
      log (LOG_ERR, "unable to peek message");
      break;
    }

    if (got_msg) {
      switch (msg.header.type) {
        case QUIT_MESSAGE:
          log (LOG_INFO, "sensor service quiting");
          run = 0;
      }
    }
  }

out3:
  sensor_manager_destroy (&sensor_mgr);

out2:
  message_queue_unregister_handler_all (msg_queue, &msg_handler);

out1:
  message_handler_destroy (&msg_handler);
}
